
#include"w5500.h"
#include"spi_tx_rx.h"


uint16_t SSIZE[MAX_SOCK_NUM]={0,0,0,0,0,0,0,0}; // Max Tx buffer
uint16_t RSIZE[MAX_SOCK_NUM]={0,0,0,0,0,0,0,0}; // Max Rx buffer
uint8_t txsize[MAX_SOCK_NUM] = {2,2,2,2,2,2,2,2};//tx buffer set	K bits
uint8_t rxsize[MAX_SOCK_NUM] = {2,2,2,2,2,2,2,2};//rx buffet set  K bits

//初始化
void iinchip_init(int fd)
{
  setMR( MR_RST,fd );
}
/**
*@brief		This function is to get the Max size to receive.
*@param		s: socket number
*@return	This function return the RX buffer size has been setted
*/
uint16_t getIINCHIP_RxMAX(SOCKET s)
{
	return RSIZE[s];
}	

/**
*@brief		This function is to get the Max size to receive.
*@param		s: socket number
*@return	This function return the RX buffer size has been setted
*/
uint16_t getIINCHIP_TxMAX(SOCKET s)
{
	return SSIZE[s];
}


/**
*@brief		This function is to set up gateway IP address.
                    此功能用于设置网关IP地址。 
*@param		addr: a pointer to a 4 -byte array responsible to set the Gateway IP address 
*@return	None
*/
void setGAR(uint8_t * addr,int fd)
{
    wiz_write_buf(fd,GAR0, addr, 4);
}

/**
*@brief		This function is to get gateway IP address.
                     此函数用于获取网关IP地址
*@param		addr: a pointer to a 4 -byte array responsible to get the Gateway IP address  
*@return	None
*/
void getGAR(uint8_t * addr,int fd)
{
    wiz_read_buf(fd,GAR0, addr, 4);
}

/**
*@brief 	This function is to set up SubnetMask address
                    此功能用于设置子网掩码地址 
*@param		addr: a pointer to a 4 -byte array responsible to set the subway IP address.  
*@return	None
*/
void setSUBR(uint8_t * addr,int fd)
{   
    wiz_write_buf(fd,SUBR0, addr, 4);
}
/**
*@brief		This function is to set up MAC address.
                    此功能用于设置MAC地址。 
*@param		addr: a pointer to a 6 -byte array responsible to set the MAC address.  
*@return	None
*/
void setSHAR(uint8_t * addr,int fd)
{
  wiz_write_buf(fd,SHAR0, addr, 6);  
}

/**
*@brief		This function is to set up Source IP address.
                    此功能用于设置源IP地址
*@param		addr:a pointer to a 4 -byte array responsible to set the Source IP addres.  
*@return	None
*/
void setSIPR(uint8_t * addr,int fd)
{
    wiz_write_buf(fd,SIPR0, addr, 4);  
}

/**
*@brief		This function is to get Subnet mask.
                    此函数用于获取子网掩码 
*@param		addr:a pointer to a 4 -byte array responsible to set the Subnet mask.  
*@return	None
*/
void getSUBR(uint8_t * addr,int fd)
{
    wiz_read_buf(fd,SUBR0, addr, 4);
}

/**
*@brief		This function is to get up Source MAC .
                    此函数用于获取源MAC
*@param		addr: a pointer to a 6 -byte array responsible to get the MAC  
*@return	None
*/
void getSHAR(uint8_t * addr,int fd)
{
    wiz_read_buf(fd,SHAR0, addr, 6);
}

/**
*@brief		This function is to get up Source IP .
                    此函数用于获取源IP
*@param		addr: a pointer to a 4 -byte array responsible to get the Source IP  
*@return	None
*/
void getSIPR(uint8_t * addr,int fd)
{
    wiz_read_buf(fd,SIPR0, addr, 4);
}
/**
*@brief		This function is to set the MR register.
                    此功能用于设置模式寄存器
*@param		val: the value to set to MR  
*@return	None
*/
void setMR(uint8_t val,int fd)
{
  IINCHIP_WRITE(MR,val,fd);
}

/**
*@brief		This function is to get Interrupt register in common register.
                     此函数用于获取公共寄存器中的中断寄存器
*@param		None  
*@return	The value read from the IR register
*/
uint8_t getIR(int fd)
{
   return IINCHIP_READ(IR,fd);
}

/**
@brief		This function is to set up Retransmission time.
					If there is no response from the peer or delay in response then retransmission
					will be there as per RTR (Retry Time-value Register)setting
                    此功能用于设置重传时间。
                    如果没有来自对等方的响应或响应延迟，则重新传输
                    将按照RTR（重试时间值寄存器）设置显示 
*@param		timeout: The value write to  the RTR0 register 
*@return	None
*/
void setRTR(uint16_t timeout,int fd)
{
  IINCHIP_WRITE(RTR0,(uint8_t)((timeout & 0xff00) >> 8),fd);
  IINCHIP_WRITE(RTR1,(uint8_t)(timeout & 0x00ff),fd);
}

/**
@brief		This function is to set the number of Retransmission.
					If there is no response from the peer or delay in response then recorded time
					as per RTR & RCR register seeting then time out will occur.
                    此功能用于设置重传次数。
                    如果没有来自对等方的响应或响应延迟，则记录时间
                    根据RTR和RCR寄存器查看，然后将发生超时
*@param		retry: Times to  retry 
*@return	None
*/
void setRCR(uint8_t retry,int fd)
{
  IINCHIP_WRITE(WIZ_RCR,retry,fd);
}

/**
*@brief		This function is to the interrupt mask Enable/Disable appropriate Interrupt. ('1' : interrupt enable)
					If any bit in IMR is set as '0' then there is not interrupt signal though the bit is
					set in IR register.
                    此功能用于中断掩码启用/禁用适当的中断。（'1'：中断启用）
                    如果IMR中的任何位设置为“0”，则尽管该位为“0”，但没有中断信号
                    在IR寄存器中设置    
*@param		mask: the bits to clear
*@return	None
*/
void clearIR(uint8_t mask,int fd)
{
  IINCHIP_WRITE(IR, ~mask | getIR(fd),fd); 
}

/**
*@brief  	This function is to set the maximum segment size of TCP in Active Mode), while in Passive Mode this is set by peer
                    此功能用于设置TCP的最大段大小（在主动模式下），而在被动模式下则由对等方设置
*@param		s: socket number
*@param		Sn_MSSR: the maximum segment size
*@return	None
*/
void setSn_MSS(SOCKET s, uint16_t Sn_MSSR,int fd)
{
  IINCHIP_WRITE( Sn_MSSR0(s), (uint8_t)((Sn_MSSR & 0xff00) >> 8),fd);
  IINCHIP_WRITE( Sn_MSSR1(s), (uint8_t)(Sn_MSSR & 0x00ff),fd);
}

/**
*@brief  	This function is to set the IP Time to live(TTL) Register
                    此功能用于设置IP生存时间（TTL）寄存器
*@param		s: socket number
*@param		Sn_MSSR: the IP Time to live
*@return	None
*/
void setSn_TTL(SOCKET s, uint8_t ttl,int fd)
{    
   IINCHIP_WRITE( Sn_TTL(s) , ttl,fd);
}

/**
*@brief		This function is to read the Interrupt & Soket Status registe
                    此功能用于读取中断和Soket状态寄存器
*@param		s: socket number
*@return	socket interrupt status
*/
uint8_t getSn_IR(SOCKET s,int fd)
{
   return IINCHIP_READ(Sn_IR(s),fd);
}

/**
*@brief 	This function is to write the Interrupt & Soket Status register to clear the interrupt
                    此功能用于写入中断和Soket状态寄存器以清除中断
*@param		s: socket number
*@return  socket interrupt status
*/
void setSn_IR(uint8_t s, uint8_t val,int fd)
{
    IINCHIP_WRITE(Sn_IR(s), val,fd);
}

/**
*@brief 	This function is to get socket status
                    此函数用于获取套接字状态
*@param		s: socket number
*@return  socket status
*/
uint8_t getSn_SR(SOCKET s,int fd)
{
   return IINCHIP_READ(Sn_SR(s),fd);
}

/**
*@brief		This fuction is to get socket TX free buf size
					This gives free buffer size of transmit buffer. This is the data size that user can transmit.
					User shuold check this value first and control the size of transmitting data
                    此功能用于获得socketTX自由buf大小
                    这将提供传输缓冲区的空闲缓冲区大小。这是用户可以传输的数据大小。
                    用户先检查此值并控制传输数据的大小 
*@param		s: socket number
*@param		fd: socket number
*@return  socket TX free buf size
*/
uint16_t getSn_TX_FSR(SOCKET s,int fd)
{
  uint16_t val=0,val1=0;
  do
  {
    val1 = IINCHIP_READ(Sn_TX_FSR0(s),fd);
    val1 = (val1 << 8) + IINCHIP_READ(Sn_TX_FSR1(s),fd);
      if (val1 != 0)
    {
        val = IINCHIP_READ(Sn_TX_FSR0(s),fd);
        val = (val << 8) + IINCHIP_READ(Sn_TX_FSR1(s),fd);
    }
  } while (val != val1);
   return val;
}

/**
*@brief		This fuction is to give size of received data in receive buffer.
                    此功能用于给出接收缓冲区中接收数据的大小
*@param		s: socket number
*@param		fd: fd
*@return  socket TX free buf size
*/
uint16_t getSn_RX_RSR(SOCKET s,int fd)
{
  uint16_t val=0,val1=0;
  do
  {
    val1 = IINCHIP_READ(Sn_RX_RSR0(s),fd);
    val1 = (val1 << 8) + IINCHIP_READ(Sn_RX_RSR1(s),fd);
    if(val1 != 0)
    {
        val = IINCHIP_READ(Sn_RX_RSR0(s),fd);
        val = (val << 8) + IINCHIP_READ(Sn_RX_RSR1(s),fd);
    }
  } while (val != val1);
   return val;
}

/**
*@brief   This function is being called by send() and sendto() function also.

					This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
					register. User should read upper byte first and lower byte later to get proper value.
                    这个函数也被send（）和sendto（）函数调用。
                    此函数读取Tx写入指针寄存器，并在复制缓冲区中的数据后更新Tx写入指针
                    登记用户应该先读取高位字节，然后读取低位字节，以获得正确的值。
*@param		s: socket number
*@param		data: data buffer to send
*@param		len: data length
*@return  socket TX free buf size
*/
void send_data_processing(SOCKET s, uint8_t *data, uint16_t len,int fd)
{
  uint16_t ptr =0;
  uint32_t addrbsb =0;
  if(len == 0)
  {
    printf("CH: %d Unexpected1 length 0\r\n", s);
    return;
  }
   
  ptr = IINCHIP_READ( Sn_TX_WR0(s),fd);
  ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_TX_WR1(s),fd);

  addrbsb = (uint32_t)(ptr<<8) + (s<<5) + 0x10;
  wiz_write_buf(fd,addrbsb, data, len);
  
  ptr += len;
  IINCHIP_WRITE( Sn_TX_WR0(s) ,(uint8_t)((ptr & 0xff00) >> 8),fd);
  IINCHIP_WRITE( Sn_TX_WR1(s),(uint8_t)(ptr & 0x00ff),fd);
}

/**
*@brief  	This function is being called by recv() also.
					This function read the Rx read pointer register
					and after copy the data from receive buffer update the Rx write pointer register.
					User should read upper byte first and lower byte later to get proper value.
                    recv（）也正在调用此函数。
                    此函数用于读取Rx读取指针寄存器
                    从接收缓冲区复制数据后，更新Rx写入指针寄存器。
                    用户应该先读取高位字节，然后读取低位字节，以获得正确的值
*@param		s: socket number
*@param		data: data buffer to receive
*@param		len: data length
*@return  None
*/
void recv_data_processing(SOCKET s, uint8_t *data, uint16_t len,int fd)
{
  uint16_t ptr = 0;
  uint32_t addrbsb = 0;
  
  if(len == 0)
  {
    printf("CH: %d Unexpected2 length 0\r\n", s);
    return;
  }

  ptr = IINCHIP_READ( Sn_RX_RD0(s),fd);
  ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ( Sn_RX_RD1(s),fd);

  addrbsb = (uint32_t)(ptr<<8) + (s<<5) + 0x18;
  wiz_read_buf(fd,addrbsb, data, len);
  ptr += len;

  IINCHIP_WRITE( Sn_RX_RD0(s), (uint8_t)((ptr & 0xff00) >> 8),fd);
  IINCHIP_WRITE( Sn_RX_RD1(s), (uint8_t)(ptr & 0x00ff),fd);
}

/**
*@brief		This function set the transmit & receive buffer size as per the channels is used
*@Note: 	TMSR and RMSR bits are as follows\n
					Maximum memory size for Tx, Rx in the W5500 is 16K Bytes,\n
					In the range of 16KBytes, the memory size could be allocated dynamically by each channel.\n
					Be attentive to sum of memory size shouldn't exceed 8Kbytes\n
					and to data transmission and receiption from non-allocated channel may cause some problems.\n
					If the 16KBytes memory is already  assigned to centain channel, \n
					other 3 channels couldn't be used, for there's no available memory.\n
					If two 4KBytes memory are assigned to two each channels, \n
					other 2 channels couldn't be used, for there's no available memory.\n
                    此功能根据使用的通道设置发送和接收缓冲区大小
                    *@注意：TMSR和RMSR位如下所示\n
                    W5500中Tx、Rx的最大内存大小为16K字节，\n
                    在16KB的范围内，每个通道都可以动态分配内存大小。\n
                    注意内存大小之和不应超过8KB\n
                    而从非分配信道进行数据传输和接收可能会引起一些问题。\n
                    如果16KB内存已分配给中央信道，\n
                    其他3个通道无法使用，因为没有可用内存。\n
                    如果为每个通道分配了两个4KB内存，\n
                    无法使用其他2个通道，因为没有可用内存。\n
*@param		tx_size: tx buffer size to set=tx_size[s]*(1024)
*@param		rx_size: rx buffer size to set=rx_size[s]*(1024)
*@return	None
*/
void socket_buf_init( uint8_t * tx_size, uint8_t * rx_size ,int fd)
{
  uint16_t i;
  uint16_t ssum=0,rsum=0;
 
  for (i = 0 ; i < MAX_SOCK_NUM; i++)       // Set the size, masking and base address of Tx & Rx memory by each channel
  {
          IINCHIP_WRITE( (Sn_TXMEM_SIZE(i)), tx_size[i],fd);
          IINCHIP_WRITE( (Sn_RXMEM_SIZE(i)), rx_size[i],fd);
          
#ifdef __DEF_IINCHIP_DBG__
         printf("tx_size[%d]: %d, Sn_TXMEM_SIZE = %d\r\n",i, tx_size[i], IINCHIP_READ(Sn_TXMEM_SIZE(i)));
         printf("rx_size[%d]: %d, Sn_RXMEM_SIZE = %d\r\n",i, rx_size[i], IINCHIP_READ(Sn_RXMEM_SIZE(i)));
#endif
    SSIZE[i] = ( uint16_t)(0);
    RSIZE[i] = ( uint16_t)(0);
	
    if (ssum <= 16384)
    {
			SSIZE[i] = ( uint16_t)tx_size[i]*(1024);
    }

		if (rsum <= 16384)
		{
			RSIZE[i]=( uint16_t)rx_size[i]*(1024);
    }
			ssum += SSIZE[i];
			rsum += RSIZE[i];

  }
}